﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using YJKRGeometry;
using TopologySearch;

namespace YJKArch.Aproll.BaseLineManage
{
	public class PathAutoSearcher
	{
		public PathAutoSearcher(ExternalCommandData cmdData)
		{
			this.m_ComdData = cmdData;
			this.m_UIApp = cmdData.Application;
			this.m_UIDoc = this.m_UIApp.ActiveUIDocument;
			this.m_App = this.m_UIApp.Application;
			this.m_doc = this.m_UIDoc.Document;
		}

		public bool SelectExternalProfile(ref List<Curve> selFaceProfile)
		{
			bool result;
			try
			{
				List<Wall> list = new List<Wall>();
				this.GetWalls(this.m_doc, ref list);
				List<FamilyInstance> list2 = new List<FamilyInstance>();
				this.GetColumns(this.m_doc, ref list2);
				List<Solid> list3 = new List<Solid>();
				foreach (Wall element in list)
				{
					List<Solid> elementSolids = this.GetElementSolids(element);
					list3.AddRange(elementSolids);
				}
				foreach (FamilyInstance element2 in list2)
				{
					List<Solid> elementSolids2 = this.GetElementSolids(element2);
					list3.AddRange(elementSolids2);
				}
				CurveArray curveArray = new CurveArray();
				PathAutoSearcher.GetSolidProjection(this.m_doc, list3, ref curveArray);
				List<Pole2D> list4 = new List<Pole2D>();
				foreach (object obj in curveArray)
				{
					Pole2D item = Pole2D.TransformWallToStructure2DPole((Curve)obj, ElementId.InvalidElementId, 0.0, 0.0);
					list4.Add(item);
				}
				foreach (List<Curve> collection in new StructureLoopSearcher(this.m_ComdData, 0.001).GetFullFloorEdgeLoops(list4, StructureLoopSearcher.SearchEdgeLocation.SEL_Outside))
				{
					selFaceProfile.AddRange(collection);
				}
				result = true;
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		private void GetWalls(Autodesk.Revit.DB.Document doc, ref List<Wall> selWalls)
		{
			foreach (Element element in new FilteredElementCollector(doc, doc.ActiveView.Id).OfClass(typeof(Wall)).ToElements())
			{
				Wall item = element as Wall;
				selWalls.Add(item);
			}
		}

		private void GetColumns(Autodesk.Revit.DB.Document doc, ref List<FamilyInstance> selColumns)
		{
			foreach (Element element in new FilteredElementCollector(doc, doc.ActiveView.Id).OfCategory(BuiltInCategory.OST_Columns).OfClass(typeof(FamilyInstance)).ToElements())
			{
				FamilyInstance item = element as FamilyInstance;
				selColumns.Add(item);
			}
			foreach (Element element2 in new FilteredElementCollector(doc, doc.ActiveView.Id).OfCategory(BuiltInCategory.OST_StructuralColumns).OfClass(typeof(FamilyInstance)).ToElements())
			{
				FamilyInstance item2 = element2 as FamilyInstance;
				selColumns.Add(item2);
			}
		}

		private List<Solid> GetElementSolids(Element element)
		{
			Options options = this.m_UIApp.Application.Create.NewGeometryOptions();
			options.DetailLevel = (ViewDetailLevel)3;
			options.IncludeNonVisibleObjects = true;
			GeometryElement geometryElement;
			if (element.GetType() == typeof(FamilyInstance))
			{
				FamilyInstance familyInstance = element as FamilyInstance;
				geometryElement = familyInstance.GetOriginalGeometry(options);
				geometryElement = geometryElement.GetTransformed(familyInstance.GetTransform());
			}
			else
			{
				geometryElement = element.get_Geometry(options);
			}
			List<Solid> list = new List<Solid>();
			if (null == geometryElement)
			{
				return list;
			}
			foreach (GeometryObject geometryObject in geometryElement)
			{
				if (!(geometryObject.GetType() != typeof(Solid)))
				{
					Solid solid = geometryObject as Solid;
					if (solid != null && !Geometry.LessThan(solid.Volume, 0.001))
					{
						list.Add(solid);
					}
				}
			}
			return list;
		}

		public static void GetSolidProjection(Autodesk.Revit.DB.Document doc, List<Solid> solids, ref CurveArray curveAry)
		{
			foreach (Solid solid in solids)
			{
				foreach (object obj in solid.Faces)
				{
					Face face = (Face)obj;
					if (!(face.GetType() != typeof(PlanarFace)))
					{
						PlanarFace planarFace = face as PlanarFace;
						if (Geometry.IsEqual(planarFace.FaceNormal(), XYZ.BasisZ))
						{
							PathAutoSearcher.GetPlanarFaceProjection(doc, planarFace, ref curveAry);
						}
					}
				}
			}
		}

		private static void GetPlanarFaceProjection(Autodesk.Revit.DB.Document doc, PlanarFace pFace, ref CurveArray curveAry)
		{
			foreach (object obj in pFace.EdgeLoops)
			{
				foreach (object obj2 in ((EdgeArray)obj))
				{
					Curve curve = ((Edge)obj2).AsCurve();
					curveAry.Append(curve);
				}
			}
		}

		private ExternalCommandData m_ComdData;

		private UIApplication m_UIApp;

		private UIDocument m_UIDoc;

		private Application m_App;

		private Autodesk.Revit.DB.Document m_doc;
	}
}
